<?php
/**
 * 核心基类
 */
namespace Core\Lib;
use Core\Lib\Service;
use Core\Lib\ServicePool;
final class Core {
    /**
     * 对象实例
     * @var object
     */
    private static $_instance = null;
    
    /**
     * 配置
     * @var array 
     */
    public static $config   = [];      
    
    /**
     * 语言包
     * @var array 
     */
    public static $lang     = [];
    
    /**
     * 构造函数，私有，阻止外部new对象
     */
    private function __construct(){
        // 加载配置
        $core_config = file_exists(CORE_PATH . '/Conf/config.php') ? require_once CORE_PATH . '/Conf/config.php' : [];              // 核心配置
        $application_config = file_exists(ROOT_PATH . '/Conf/config.php') ? require_once ROOT_PATH . '/Conf/config.php' : [];       // 应用配置
        self::$config = array_merge($core_config, $application_config);

        // 加载语言包
        $lang_type = array_key_exists('LANG', self::$config) ? strtolower(self::$config['LANG']) : 'zh-cn';
        $lang_file = ROOT_PATH . '/Lang/' . $lang_type . '.php';        // 语言包文件
        self::$lang = file_exists($lang_file) ? require_once $lang_file : [];
        
        // 函数库加载
        require_once CORE_PATH . '/Common/function.php';        // 核心函数库
        if(file_exists(ROOT_PATH . '/Common/function.php')) require_once ROOT_PATH . '/Common/function.php';        // 应用函数库
        
        // 初始化服务
        $this->_initializeService();
    }
    
    /**
     * 阻止外部克隆对象
     */
    public function __clone(){
        trigger_error('Clone is not allow', E_USER_WARNING);
    }
    
    /**
     * 初始化远程服务
     */
    private function _initializeService(){
        $service_config = config('SERVICES', []);
        foreach($service_config as $s_v){
            ServicePool::pushService(Service::instance($s_v));
        }
    }
    
    /**
     * 全局初始化
     */
    public static function initialize(){
        if(!self::$_instance instanceof self){
            self::$_instance = new self();
        }
        
        return self::$_instance;
    }
    
    /**
     * 运行服务
     * @param object $server        运行服务对象
     */
    public function runtime($server){
        echo "文件服务器已启动！".$server->host.":".$server->port."\n";
    }
    
    /**
     * 请求路由
     * @param object $request   请求对象
     * @param object $response  响应对象
     * @param object $server    运行服务对象
     */
    public function route($request, $response, $server){
        global $__request, $__response;
        $__request = $request;
        $__response = $response;
        self::$_instance->server = $server;
        
        // 请求类型;GET/POST/PUT/DEUETE
        $method = $request->server['request_method'];

        // 请求参数接收名
        $method_var_arr = config('METHOD_VAR');
        $method_var = $method_var_arr[strtoupper($method)];

        // 请求参数
        $method_params = property_exists($request, $method_var) ? $request->$method_var : [];

        // 资源符
        $uri = config(strtoupper($method));
        if(!$uri) return "URI Not Found!";

        // 路由信息
        $route_info = explode('/', $uri[$request->server['request_uri']]);

        $route_class    = config('DEFAULT_ROUTE_CLASS', self::$config['DEFAULT_ROUTE_CLASS']);      // 路由处理类
        $route_action   = config('DEFAULT_ROUTE_ACTION', self::$config['DEFAULT_ROUTE_ACTION']);     // 路由处理方法
        
        switch(count($route_info)){
            case 1:
                $route_action   = $route_info[0];       // 路由处理方法
                break;
            case 2:
                $route_class    = $route_info[0];       // 路由处理类
                $route_action   = $route_info[1];       // 路由处理方法
                break;
        }

        // 创建路由对象
        $route = self::$_instance->controller($route_class);
        
        // 执行路由操作
        return $route->$route_action();   
    }
    
    /**
     * 控制器实例
     * @param string $name    控制器名
     * @param string $layer   控制器层
     * @return instance
     */
    public function controller($name='', $layer=''){
        if(!$name) return new \stdClass ();
        static $_controllers = [];
        $layer = $layer ? $layer : config('DEFAULT_CONTROLLER_LAYER', self::$config['DEFAULT_CONTROLLER_LAYER']);
        $hash_name = $name.$layer;
        if(isset($_controllers[$hash_name])) {
            if(method_exists($_controllers[$hash_name], 'initialize')) $_controllers[$hash_name]->initialize();
            return $_controllers[$hash_name];
        }
        
        $controller = $layer.'\\'.$name.$layer; 
        if(!class_exists($controller)){
            return new \stdClass();
        }
        
        // 不存在实例池
        return $_controllers[$hash_name] = new $controller();
    }
    
    /**
     * 模型实例
     * @param string $name   模型名
     * @param string $layer  模型层
     * @return instance
     */
    public function model($name='', $layer=''){
        if(!$name) return new \stdClass ();
        
        static $_models = [];
        $layer = $layer ? $layer : config('DEFAULT_MODEL_LAYER', self::$config['DEFAULT_MODEL_LAYER']);
        $hash_name = $name.$layer;
        
        if(isset($_models[$hash_name])) {
            if(method_exists($_models[$hash_name], 'initialize')) $_models[$hash_name]->initialize();
            return $_models[$hash_name];
        }
        
        $_model = $layer.'\\' . $name.$layer; 
        if(!class_exists($_model)){
            return new \stdClass();
        }
        return $_models[$hash_name] = new $_model();
    }
    
    /**
     * 逻辑实例
     * @param string $name   逻辑名
     * @param string $layer  逻辑层
     * @return instance
     */
    public function logic($name='', $layer=''){
        if(!$name) return new \stdClass ();
        
        static $_logics = [];
        $layer = $layer ? $layer : config('DEFAULT_LOGIC_LAYER', self::$config['DEFAULT_LOGIC_LAYER']);
        $hash_name = $name.$layer;
        
        if(isset($_logics[$hash_name])) {
            if(method_exists($_logics[$hash_name], 'initialize')) $_logics[$hash_name]->initialize();
            return $_logics[$hash_name];
        }
        
        $logic = $layer.'\\' . $name.$layer; 
        if(!class_exists($logic)){
            return new \stdClass();
        }
        return $_logics[$hash_name] = new $logic();
    }
    
    /**
     * 服务实例
     * @param string $service_id        服务ID
     * @return instance
     */
    public function service($service_id){
        $service = ServicePool::getService($service_id);
        if(!$service){
            trigger_error('Server Error:'.$service_id.' not exists.');
        }
        return $service->getServiceInstance();
    }
}